# -*- encoding:utf8 -*-
from datetime import datetime
from workday import get_max_workday,get_exp_workdays
from attendance.convert import date2str,str2date,t2i,i2day,i2t
from attendance.models import AttendRecord,AttendReport,LeaveModel,LeaveApplication
from attendance.tool_func import get_or_new

def report(staff, duedate=None):
    """统计员工考勤。
    Args:
    staff:员工ID
    duedate:截止日期，例如2015-10-20,则统计2015-10-01 <--->2015-10-20的考勤情况
    max_worktime:员工中最大的工作时间(单位分钟):day*8*60,用于计算全勤
    
    Return:
    所有结果存放AttendReport数据表
    """
    if duedate is None:
        duedate=datetime.now().date()
    duestr=date2str(duedate)
    max_workday=get_max_workday(duestr)
    max_worktime = max_workday * 60 * 8
    firstday = date2str(duedate.replace(day=1))
    firsttime=firstday+' 00:00'
    duetime=duestr+' 00:00'
    
    # 统计迟到
    dc_attend= report_attend(staff,firstday,duedate)
   
    # 统计假期
    dc_leave=report_leave(staff,firsttime,duetime)
    
    person_leave,sick,annual=dc_leave['person_leave'],dc_leave['sick_leave'],dc_leave['annual_leave']
    other_paid_leave,swap_off,miss_check=dc_leave['other_paid_leave'],dc_leave['swap_off'],dc_leave['miss_check']
    late1,late2,late3,late4=dc_attend['late1'],dc_attend['late2'],dc_attend['late3'],dc_attend['late4']
    late_team,absent,early_leave=dc_attend['late_team'],dc_attend['absent'],dc_attend['early_leave']
    late_person,overtime=dc_attend['late_person'],dc_attend['overtime']
    
    exp_worktime = get_exp_workdays(duestr, staff.employee_id) * 8 * 60
    act_worktime = report_act_worktime(exp_worktime, person_leave, sick, absent)

    # 补贴扣除天数
    over_late3_days=late3 + late4
    allow_subtime = report_allow_subtime(person_leave, sick, annual,
                                                     other_paid_leave, over_late3_days)
    allow_time = report_allowtime(exp_worktime, allow_subtime)
    leave_time = report_leavetime(person_leave, sick, annual,
                                              other_paid_leave, swap_off)
    paid_leave = report_paid_leave(annual, other_paid_leave)
    deduction = report_deduction(absent)
    # 考勤处理：书面警告，口头警告
    late2up = late2 + late3 + late3 + late4
    late_all=late1+late2up
    late_act_times = late_team
    process = report_process(late2up, late_act_times, absent)

    worktype = 'FTE' if staff.emp_type == 'L' else 'not_FTE'
    workshift = staff.workshift
    full_attend = report_full_attend(worktype, workshift, exp_worktime, max_worktime,
                                                 person_leave, sick, paid_leave, late_all, absent, early_leave)

    report_row = get_or_new(AttendReport, staff=staff, start_date=firstday)
    report_row.due_date = duestr
    report_row.person_leave = i2day(person_leave)
    report_row.sick = i2day(sick)
    report_row.annual = i2day(annual)
    report_row.other_paid_leave = i2day(other_paid_leave)
    report_row.swap_off = i2t(swap_off)
    report_row.paid_leave = i2day(paid_leave)
    report_row.miss_check=str(miss_check)
    report_row.late1 = str(late1)
    report_row.late2 = str(late2)
    report_row.late3 = str(late3)
    report_row.late4 = str(late4)
    report_row.late_person = i2t(late_person)
    report_row.late_team = i2t(late_team)
    report_row.overtime = i2t(overtime)
    report_row.exp_workday = i2day(exp_worktime)
    report_row.act_workday = i2day(act_worktime)
    report_row.allow_day = i2day(allow_time)
    report_row.leave_day = i2day(leave_time)
    report_row.deduction_day = i2day(deduction)
    report_row.absent = i2day(absent)
    report_row.early_leave = i2t(early_leave)
    report_row.full_attend = full_attend
    report_row.process = process
    report_row.save()

def report_attend(staff,firstday,duedate):
    late1=0
    late2=0
    late3=0
    late4=0
    absent=0
    overtime=0
    late_person=0
    late_team=0
    early_leave=0
    for row in AttendRecord.objects.filter(staff=staff, date__gte=firstday, date__lte=duedate):
        absent += t2i(row.absent)
        if row.late_level:
            if row.late_level == 'late1':
                late1 += 1
            elif row.late_level == 'late2':
                late2 += 1
            elif row.late_level == 'late3':
                late3 += 1
            elif row.late_level == 'late4':
                late4 += 1

        overtime += t2i(row.overtime)
        late_person += t2i(row.late_person)
        late_team += t2i(row.late_team)
        #workday, shift = is_workday(row.date)
        early_leave+=t2i(row.early_leave)    
    return {'late1':late1,
            'late2':late2,
            'late3':late3,
            'late4':late4,
            'overtime':overtime,
            'late_person':late_person,
            'late_team':late_team,
            'early_leave':early_leave,
            'absent':absent
        }
def report_leave(staff,firsttime,duetime):
    annual=0
    sick=0
    swap_off=0
    person_leave=0
    other_paid_leave=0
    miss_check=0
    for leave in LeaveModel.objects.filter(staff=staff, start_time__lte=duetime, start_time__gte=firsttime):
        if leave.category == 'annual_leave':
            annual += leave.span()
        elif leave.category == 'sick_leave':
            sick += leave.span()
        elif leave.category == 'swap_off':
            swap_off += leave.span()
        elif leave.category == 'personal_leave':
            person_leave += leave.span()
        elif leave.category in ['birthday_leave','others']:
            other_paid_leave += leave.span()     # Todo 确认 other_padi_leave的种类

    for miss in LeaveApplication.objects.filter(staff=staff,end_time__lte=duetime, start_time__gte=firsttime,
                                                category='miss_check',status='approved'):
        miss_check+=1    
    return {'annual_leave':annual,
            'sick_leave':sick,
            'swap_off':swap_off,
            'person_leave':person_leave,
            'other_paid_leave':other_paid_leave,
            'miss_check':miss_check
        }

def report_max_worktime(days):
    """
    所有员工中，当月应该上班的最大天数。
    普通员工应该上班的天数一般都是最大天数，
    但是新入职的员工，却不是
    """
    cnt = 0
    for day in days:
        workday, _ = is_workday(day)
        if workday:
            cnt += 1
    return cnt * 8 * 60


def report_expect_worktime(days, empid):
    """根据员工id，日期，计算员工应该上班的天数
    例如，9月7日入职的员工，他应该上班的时间就不包括9.1-9.6
    这个，可能需要单独来设置！
    现在暂时这么写
    """
    cnt = 0
    for day in days:
        workday, _ = is_workday(day)
        if workday:
            cnt += 1
    return cnt * 8 * 60


def report_act_worktime(exp_worktime, person_leave, sick_leave, absent):
    """实际工作小时数
    @exp_workday:应该上班的天数
    """
    return exp_worktime - person_leave - sick_leave - absent


def report_allowtime(exp_worktime, allow_subtime):
    """补贴小时数
    """
    return exp_worktime - allow_subtime


def report_allow_subtime(person_leave, sick_leave, annual_leave, other_paid_leave, over_late3_days):
    """补贴扣除时间
    """
    return person_leave + sick_leave + annual_leave + other_paid_leave + over_late3_days * 8 * 60


def report_leavetime(person_leave, sick_leave, annual_leave, other_paid_leave, swap_off):
    """请假总天数
    """
    return person_leave + sick_leave + annual_leave + other_paid_leave + swap_off


def report_paid_leave(annual_leave, other_paid_leave):
    """所有带薪假小时数
    """
    return annual_leave + other_paid_leave


def report_full_attend(worktype, workshift, exp_worktime, max_worktime, person_leave, sick_leave, paid_leave, late_all,
                       absent, early_leave):
    """是否全勤
    """
    if worktype != "FTE":
        return False
    elif workshift == 'Flexible':
        return False
    elif exp_worktime < max_worktime:
        return False
    elif person_leave + sick_leave > 0:
        return False
    elif paid_leave > 5 * 8 * 60:  # 带薪假超过5天
        return False
    elif late_all > 0:
        return False
    elif absent > 0:
        return False
    elif early_leave > 0:
        return False
    else:
        return True


def report_deduction(absent):
    """扣款小时数
    """
    return absent


def report_process(late_cnt, late_act_times, absent):
    """考勤处理结果
    """
    if absent > 0:
        return u'书面警告'
    elif 6 >= late_cnt > 3 and late_act_times > 120:
        return u'口头警告'
    elif 6 < late_cnt and 240 < late_act_times:
        return u'书面警告'
    else:
        return ''